package com.dt.platform.oa.service.impl;

import javax.annotation.Resource;

import com.dt.platform.constants.enums.common.StatusEnableEnum;
import com.dt.platform.constants.enums.oa.ProjectStatusEnum;
import com.dt.platform.constants.enums.oa.ProjectUserStatusEnum;
import com.dt.platform.domain.oa.*;
import com.dt.platform.oa.service.IProjectRcdService;
import com.dt.platform.oa.service.IProjectService;
import com.dt.platform.oa.service.IProjectUserService;
import com.github.foxnic.commons.lang.StringUtil;
import com.github.foxnic.dao.data.Rcd;
import com.github.foxnic.sql.expr.OrderBy;
import org.github.foxnic.web.session.SessionUser;
import org.simpleframework.xml.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.github.foxnic.dao.entity.ReferCause;
import com.github.foxnic.commons.collection.MapUtil;

import java.util.*;


import com.github.foxnic.api.transter.Result;
import com.github.foxnic.dao.data.PagedList;
import com.github.foxnic.dao.entity.SuperService;
import com.github.foxnic.dao.spec.DAO;
import java.lang.reflect.Field;
import com.github.foxnic.commons.busi.id.IDGenerator;
import com.github.foxnic.sql.expr.ConditionExpr;
import com.github.foxnic.api.error.ErrorDesc;
import com.github.foxnic.dao.excel.ExcelWriter;
import com.github.foxnic.dao.excel.ValidateResult;
import com.github.foxnic.dao.excel.ExcelStructure;
import java.io.InputStream;
import com.github.foxnic.sql.meta.DBField;
import com.github.foxnic.dao.data.SaveMode;
import com.github.foxnic.dao.meta.DBColumnMeta;
import com.github.foxnic.sql.expr.Select;
import com.dt.platform.oa.service.IProjectPhaseService;
import org.github.foxnic.web.framework.dao.DBConfigs;

/**
 * <p>
 * 项目阶段服务实现
 * </p>
 * @author 金杰 , maillank@qq.com
 * @since 2025-06-19 08:34:10
*/


@Service("OaProjectPhaseService")

public class ProjectPhaseServiceImpl extends SuperService<ProjectPhase> implements IProjectPhaseService {

	@Autowired
	private IProjectRcdService projectRcdService;

	@Autowired
	private IProjectUserService projectUserService;

	@Autowired
	private IProjectService projectService;

	/**
	 * 注入DAO对象
	 * */
	@Resource(name=DBConfigs.PRIMARY_DAO) 
	private DAO dao=null;

	/**
	 * 获得 DAO 对象
	 * */
	public DAO dao() { return dao; }




	@Override
	public Object generateId(Field field) {
		return IDGenerator.getSnowflakeIdString();
	}

	/**
	 * 添加，根据 throwsException 参数抛出异常或返回 Result 对象
	 *
	 * @param projectPhase  数据对象
	 * @param throwsException 是否抛出异常，如果不抛出异常，则返回一个失败的 Result 对象
	 * @return 结果 , 如果失败返回 false，成功返回 true
	 */
	@Override
	public Result insert(ProjectPhase projectPhase,boolean throwsException) {

		String cUserId=SessionUser.getCurrent().getActivatedEmployeeId();
		if(!StringUtil.isBlank(projectPhase.getTplStatus())){
			if(StatusEnableEnum.ENABLE.code().equals(projectPhase.getTplStatus())){
				dao.execute("insert into oa_project_phase(leader_id,id,project_id,name,rk,sdate,edate) select '"+cUserId+"',uuid(),'"+projectPhase.getProjectId()+"',name,rk+1000,now(),now() from oa_project_phase where project_id='oa_project_phase_tpl' and deleted=0 and tpl='tpl1' and tpl_status='enable' ");
				this.resetOrder(projectPhase.getProjectId());
				return ErrorDesc.success();
			}
		}

		projectPhase.setRk(nextOrderValue(projectPhase.getProjectId()));
		Result r=super.insert(projectPhase,throwsException);



		if(r.isSuccess()){
			List<String> strList=projectPhase.getPartUserStrList();
			if(strList!=null){
				List<ProjectUser> userList=new ArrayList<>();
				for(int i=0;i<strList.size();i++){
					ProjectUserVO userQuery=new ProjectUserVO();
					userQuery.setUserId(strList.get(i));
					userQuery.setProjectId(projectPhase.getId());
					ProjectUser sourceUser=projectUserService.queryEntity(userQuery);
					ProjectUser user=new ProjectUser();
					user.setOwnType("phase");
					user.setUserId(strList.get(i));
					user.setProjectId(projectPhase.getId());
					if(sourceUser==null){
						user.setInTime(new Date());
						user.setStatus(ProjectUserStatusEnum.IN.code());
					}else{
						user.setStatus(sourceUser.getStatus());
						user.setInTime(sourceUser.getInTime());
						user.setOutTime(new Date());
					}
					userList.add(user);
				}
				dao.execute("delete from oa_project_user where project_id=?",projectPhase.getId());
				if(userList.size()>0){
					projectUserService.insertList(userList);
				}
			}
		}
		return r;
	}

	@Override
	public Result action(String id, String action,String ct) {
		if(StringUtil.isBlank(id)){
			return ErrorDesc.failureMessage("为选择当前阶段");
		}
		ProjectPhase phase=this.getById(id);
		String cUserId=SessionUser.getCurrent().getActivatedEmployeeId();
		if("up".equals(action)){
			if(phase.getRk()==1){
				return ErrorDesc.success();
			}
			//开始调整
			dao.execute("update oa_project_phase set rk=rk+1 where project_id=? and rk=?",phase.getProjectId(),phase.getRk()-1);
			dao.execute("update oa_project_phase set rk=rk-1 where id=?",id);
			resetOrder(phase.getProjectId());
		}else if ("down".equals(action)){
			int max=nextOrderValue(phase.getProjectId());
			if(max==phase.getRk()){
				return ErrorDesc.success();
			}
			//开始调整
			dao.execute("update oa_project_phase set rk=rk-1 where project_id=? and rk=?",phase.getProjectId(),phase.getRk()+1);
			dao.execute("update oa_project_phase set rk=rk+1 where id=?",id);
			resetOrder(phase.getProjectId());
		}else if ("finish".equals(action)){
			Project project=projectService.getById(phase.getProjectId());
			if( ProjectStatusEnum.ACTING.code().equals(project.getProjectStatus())
					||ProjectStatusEnum.WAIT.code().equals( project.getProjectStatus())){
			}else{
				return ErrorDesc.failureMessage("不可进行操作，项目可能已关闭或结束");
			}
			boolean canDoIt=false;
			if(projectService.userInProjectLeader(cUserId,phase.getProjectId())){
				canDoIt=true;
			}
			if(!canDoIt){
				if(projectService.userInProjectPhase(cUserId,phase.getProjectId())){
					canDoIt=true;
				}
			}
			if(canDoIt){
				//下一个阶段
				ProjectRcd rcd=new ProjectRcd();
				rcd.setRcdTime(new Date());
				rcd.setOwnerType("phase");
				rcd.setOwnerId(phase.getProjectId());
				rcd.setUserId(cUserId);
				rcd.setContent(SessionUser.getCurrent().getRealName()+"确认完成了【"+phase.getName()+"】的工作。操作意见:"+(ct==null?"无":ct));
				projectRcdService.insert(rcd,false);

				Rcd rs=dao.queryRecord("select * from oa_project_phase where deleted=0 and project_id=? and rk=?",phase.getProjectId(),phase.getRk()+1);
				if(rs==null){
					dao.execute("update oa_project set project_status=?, cur_phase='' where id=?",ProjectStatusEnum.FINISH.code(),phase.getProjectId());
					//没有项目了
					ProjectRcd rcd2=new ProjectRcd();
					rcd2.setRcdTime(new Date());
					rcd2.setOwnerType("project");
					rcd2.setOwnerId(phase.getProjectId());
					rcd2.setUserId(cUserId);
					rcd2.setContent(SessionUser.getCurrent().getRealName()+"确认完成了项目。操作意见:"+(ct==null?"无":ct));
				}else{
					dao.execute("update oa_project set cur_phase=? where id=?",rs.getString("id"),phase.getProjectId());
				}
			}else{
				return ErrorDesc.failureMessage("只有阶段负责人和项目经理才有权限");
			}
		}else if ("rollback".equals(action)){
			Project project=projectService.getById(phase.getProjectId());
			if( ProjectStatusEnum.ACTING.code().equals(project.getProjectStatus())
					||ProjectStatusEnum.WAIT.code().equals( project.getProjectStatus())){
			}else{
				return ErrorDesc.failureMessage("不可进行操作，项目可能已关闭或结束");
			}
			boolean canDoIt=false;
			if(projectService.userInProjectLeader(cUserId,phase.getProjectId())){
				canDoIt=true;
			}
			if(!canDoIt){
				if(projectService.userInProjectPhase(cUserId,phase.getProjectId())){
					canDoIt=true;
				}
			}
			if(canDoIt){
				if(phase.getRk()==1){
					return ErrorDesc.failureMessage("当前阶段无法在进行退回");
				}else{
					Rcd rs=dao.queryRecord("select * from oa_project_phase where deleted=0 and project_id=? and rk=?",phase.getProjectId(),phase.getRk()-1);
					if(rs==null){
						return ErrorDesc.failureMessage("没有找到回退的阶段节点");
					}else{
						ProjectRcd rcd=new ProjectRcd();
						rcd.setRcdTime(new Date());
						rcd.setOwnerType("phase");
						rcd.setOwnerId(phase.getProjectId());
						rcd.setUserId(cUserId);
						rcd.setContent(SessionUser.getCurrent().getRealName()+"在阶段【"+phase.getName()+"】执行了回退操作。操作意见:"+(ct==null?"无":ct));
						projectRcdService.insert(rcd,false);
						dao.execute("update oa_project set cur_phase=? where id=?",rs.getString("id"),phase.getProjectId());
					}
				}
			}else{
				return ErrorDesc.failureMessage("只有阶段负责人和项目经理才有权限");
			}
		}
		return ErrorDesc.success();
	}

	private Result resetOrder(String projectId){
		ProjectPhaseVO phaseVO=new ProjectPhaseVO();
		phaseVO.setProjectId(projectId);
		OrderBy order=new OrderBy();
		order.asc("rk");
		List<ProjectPhase> list=this.queryList(phaseVO,order);
		for(int i=0;i<list.size();i++){
			dao.execute("update oa_project_phase set rk=? where id=?",(i+1),list.get(i).getId());
		}
		return ErrorDesc.success();
	}

	private int nextOrderValue(String projectId){
		String sql="select ifnull(max(rk),0) value from oa_project_phase where deleted=0 and project_id=?";
		Rcd rs=dao.queryRecord(sql,projectId);
		if(rs==null){
			return 1;
		}else{
			return rs.getInteger("value")+1;
		}
	}


	/**
	 * 添加，如果语句错误，则抛出异常
	 * @param projectPhase 数据对象
	 * @return 插入是否成功
	 * */
	@Override
	public Result insert(ProjectPhase projectPhase) {
		return this.insert(projectPhase,true);
	}

	/**
	 * 批量插入实体，事务内
	 * @param projectPhaseList 实体数据清单
	 * @return 插入是否成功
	 * */
	@Override
	public Result insertList(List<ProjectPhase> projectPhaseList) {
		return super.insertList(projectPhaseList);
	}

	
	/**
	 * 按主键删除项目阶段
	 *
	 * @param id 主键
	 * @return 删除是否成功
	 */
	public Result deleteByIdPhysical(String id) {

		ProjectPhase source=this.getById(id);
		Rcd rs=dao.queryRecord("select count(1) cnt from oa_project_phase where deleted=0 and project_id=?",source.getProjectId());
		if(rs.getInteger("cnt")==1){
			return ErrorDesc.failureMessage("至少保留一个项目阶段");
		}
		Rcd rs2=dao.queryRecord("select * from oa_project where id=? and deleted=0 and cur_phase=?",source.getProjectId(),id);
		if(rs2!=null){
			return ErrorDesc.failureMessage("本阶段正在进行中，不可删除");
		}


		ProjectPhase projectPhase = new ProjectPhase();
		if(id==null) return ErrorDesc.failure().message("id 不允许为 null 。");
		projectPhase.setId(id);
		try {
			boolean suc = dao.deleteEntity(projectPhase);
			return suc?ErrorDesc.success():ErrorDesc.failure();
		}
		catch(Exception e) {
			Result r= ErrorDesc.failure();
			r.extra().setException(e);
			return r;
		}
	}
	
	/**
	 * 按主键删除项目阶段
	 *
	 * @param id 主键
	 * @return 删除是否成功
	 */
	public Result deleteByIdLogical(String id) {
		ProjectPhase source=this.getById(id);
		Rcd rs=dao.queryRecord("select count(1) cnt from oa_project_phase where deleted=0 and project_id=?",source.getProjectId());
		if(rs.getInteger("cnt")==1){
			return ErrorDesc.failureMessage("至少保留一个项目阶段");
		}
		Rcd rs2=dao.queryRecord("select * from oa_project where id=? and deleted=0 and cur_phase=?",source.getProjectId(),id);
		if(rs2!=null){
			return ErrorDesc.failureMessage("本阶段正在进行中，不可删除");
		}


		ProjectPhase projectPhase = new ProjectPhase();
		if(id==null) return ErrorDesc.failure().message("id 不允许为 null 。");
		projectPhase.setId(id);
		projectPhase.setDeleted(true);
		projectPhase.setDeleteBy((String)dao.getDBTreaty().getLoginUserId());
		projectPhase.setDeleteTime(new Date());
		try {

			boolean suc = dao.updateEntity(projectPhase,SaveMode.NOT_NULL_FIELDS);
			if(suc){
				this.resetOrder(source.getProjectId());
			}
			return suc?ErrorDesc.success():ErrorDesc.failure();
		}
		catch(Exception e) {
			Result r= ErrorDesc.failure();
			r.extra().setException(e);
			return r;
		}

	}

	/**
	 * 更新，如果执行错误，则抛出异常
	 * @param projectPhase 数据对象
	 * @param mode 保存模式
	 * @return 保存是否成功
	 * */
	@Override
	public Result update(ProjectPhase projectPhase , SaveMode mode) {
		return this.update(projectPhase,mode,true);
	}

	/**
	 * 更新，根据 throwsException 参数抛出异常或返回 Result 对象
	 * @param projectPhase 数据对象
	 * @param mode 保存模式
	 * @param throwsException 是否抛出异常，如果不抛出异常，则返回一个失败的 Result 对象
	 * @return 保存是否成功
	 * */
	@Override
	public Result update(ProjectPhase projectPhase , SaveMode mode,boolean throwsException) {
		Result r=super.update(projectPhase , mode , throwsException);

		if(r.isSuccess()){
			List<String> strList=projectPhase.getPartUserStrList();
			if(strList!=null){
				List<ProjectUser> userList=new ArrayList<>();
				for(int i=0;i<strList.size();i++){
					ProjectUserVO userQuery=new ProjectUserVO();
					userQuery.setUserId(strList.get(i));
					userQuery.setProjectId(projectPhase.getId());
					ProjectUser sourceUser=projectUserService.queryEntity(userQuery);

					ProjectUser user=new ProjectUser();
					user.setOwnType("phase");
					user.setUserId(strList.get(i));
					user.setProjectId(projectPhase.getId());
					if(sourceUser==null){
						user.setInTime(new Date());
						user.setStatus(ProjectUserStatusEnum.IN.code());
					}else{
						user.setStatus(sourceUser.getStatus());
						user.setInTime(sourceUser.getInTime());
						user.setOutTime(new Date());
					}
					userList.add(user);
				}
				dao.execute("delete from oa_project_user where project_id=?",projectPhase.getId());
				if(userList.size()>0){
					projectUserService.insertList(userList);
				}
			}
		}
		return r;
	}

	/**
	 * 更新实体集，事务内
	 * @param projectPhaseList 数据对象列表
	 * @param mode 保存模式
	 * @return 保存是否成功
	 * */
	@Override
	public Result updateList(List<ProjectPhase> projectPhaseList , SaveMode mode) {
		return super.updateList(projectPhaseList , mode);
	}

	
	/**
	 * 按主键更新项目阶段
	 *
	 * @param id 主键
	 * @return 是否更新成功
	 */
	public boolean update(DBField field,Object value , String id) {
		if(id==null) throw new IllegalArgumentException("id 不允许为 null ");
		if(!field.table().name().equals(this.table())) throw new IllegalArgumentException("更新的数据表["+field.table().name()+"]与服务对应的数据表["+this.table()+"]不一致");
		int suc=dao.update(field.table().name()).set(field.name(), value).where().and("id = ? ",id).top().execute();
		return suc>0;
	}

	
	/**
	 * 按主键获取项目阶段
	 *
	 * @param id 主键
	 * @return ProjectPhase 数据对象
	 */
	public ProjectPhase getById(String id) {
		ProjectPhase sample = new ProjectPhase();
		if(id==null) throw new IllegalArgumentException("id 不允许为 null ");
		sample.setId(id);
		return dao.queryEntity(sample);
	}

	/**
	 * 等价于 queryListByIds
	 * */
	@Override
	public List<ProjectPhase> getByIds(List<String> ids) {
		return this.queryListByIds(ids);
	}

	@Override
	public List<ProjectPhase> queryListByIds(List<String> ids) {
		return super.queryListByUKeys("id",ids);
	}

	@Override
	public Map<String, ProjectPhase> queryMapByIds(List<String> ids) {
		return super.queryMapByUKeys("id",ids, ProjectPhase::getId);
	}



	/**
	 * 查询实体集合，默认情况下，字符串使用模糊匹配，非字符串使用精确匹配
	 *
	 * @param sample  查询条件
	 * @return 查询结果
	 * */
	@Override
	public List<ProjectPhase> queryList(ProjectPhaseVO sample) {
		return super.queryList(sample);
	}


	/**
	 * 分页查询实体集，字符串使用模糊匹配，非字符串使用精确匹配
	 *
	 * @param sample  查询条件
	 * @param pageSize 分页条数
	 * @param pageIndex 页码
	 * @return 查询结果
	 * */
	@Override
	public PagedList<ProjectPhase> queryPagedList(ProjectPhaseVO sample, int pageSize, int pageIndex) {
		return super.queryPagedList(sample, pageSize, pageIndex);
	}

	/**
	 * 分页查询实体集，字符串使用模糊匹配，非字符串使用精确匹配
	 *
	 * @param sample  查询条件
	 * @param condition 其它条件
	 * @param pageSize 分页条数
	 * @param pageIndex 页码
	 * @return 查询结果
	 * */
	@Override
	public PagedList<ProjectPhase> queryPagedList(ProjectPhase sample, ConditionExpr condition, int pageSize, int pageIndex) {
		return super.queryPagedList(sample, condition, pageSize, pageIndex);
	}

	/**
	 * 检查 实体 是否已经存在 , 判断 主键值不同，但指定字段的值相同的记录是否存在
	 *
	 * @param projectPhase 数据对象
	 * @return 判断结果
	 */
	public Boolean checkExists(ProjectPhase projectPhase) {
		//TDOD 此处添加判断段的代码
		//boolean exists=super.checkExists(projectPhase, SYS_ROLE.NAME);
		//return exists;
		return false;
	}

	/**
	 * 批量检查引用
	 * @param ids  检查这些ID是否又被外部表引用
	 * */
	@Override
	public <T> Map<T, ReferCause> hasRefers(List<T> ids) {
		// 默认无业务逻辑，返回此行；有业务逻辑需要校验时，请修改并使用已注释的行代码！！！
		return MapUtil.asMap(ids,new ReferCause(false));
		// return super.hasRefers(FoxnicWeb.BPM_PROCESS_INSTANCE.FORM_DEFINITION_ID,ids);
	}





}